home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / Timer.java < prev    next >
Text File  |  1998-06-30  |  9KB  |  281 lines

  1. /*
  2.  * @(#)Timer.java    1.20 98/06/08
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15.  
  16. package com.sun.java.swing;
  17.  
  18. import java.util.*;
  19. import java.awt.*;
  20. import java.awt.event.*;
  21. import java.io.Serializable;
  22. import com.sun.java.swing.event.EventListenerList;
  23.  
  24.  
  25. /**
  26.  * Object subclass that causes an action to occur at a predefined rate.  For
  27.  * example, an animation object can use a Timer as the trigger for drawing its
  28.  * next frame.  Each Timer has a list of ActionListeners and a delay (
  29.  * the time between <b>actionPerfomed()</b> calls).  When
  30.  * delay milliseconds have passed, a Timer sends the <b>actionPerformed()</b>
  31.  * message to its listeners.  This cycle repeats until
  32.  * <b>stop()</b> is called, or halts immediately if the Jimer is configured
  33.  * to send its message just once.<p>
  34.  * Using a Timer involves first creating it, then starting it using
  35.  * the <b>start()</b> method.
  36.  * <p>
  37.  * Warning: serialized objects of this class will not be compatible with
  38.  * future swing releases.  The current serialization support is appropriate 
  39.  * for short term storage or RMI between Swing1.0 applications.  It will
  40.  * not be possible to load serialized Swing1.0 objects with future releases
  41.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  42.  * baseline for the serialized form of Swing objects.
  43.  *
  44.  * @version 1.20 06/08/98
  45.  * @author unknown
  46.  */
  47. public class Timer implements Serializable
  48. {
  49.     int         initialDelay, delay;
  50.     boolean     repeats = true, coalesce = true;
  51.  
  52.     protected EventListenerList listenerList = new EventListenerList();
  53.  
  54.     boolean  eventQueued = false;
  55.  
  56.     private static boolean logTimers;
  57.  
  58.     Runnable doPostEvent = null;
  59.  
  60.     // These fields are maintained by TimerQueue.
  61.     // eventQueued can also be reset by the TimerQueue, but will only ever
  62.     // happen in applet case when TimerQueues thread is destroyed.
  63.     long expirationTime;
  64.     Timer nextTimer;
  65.     boolean running;
  66.  
  67.     /**
  68.      * Creates a Timer that will notify its listeners every
  69.      * <i>delay</i> milliseconds.
  70.      * @param delay     The number of milliseconds between listener notification
  71.      * @param listener  An initial listener
  72.      * @see #setInitialDelay
  73.      * @see #setRepeats
  74.      */
  75.     public Timer(int delay, ActionListener listener) {
  76.         super();
  77.         this.delay = delay;
  78.         this.initialDelay = delay;
  79.  
  80.         doPostEvent = new DoPostEvent();
  81.  
  82.     addActionListener(listener);
  83.     }
  84.  
  85.     /**
  86.      * DoPostEvent is a runnable class that fires actionEvents to 
  87.      * the listeners on the EventDispatchThread, via invokeLater.
  88.      * @see #post
  89.      */
  90.     class DoPostEvent implements Runnable, Serializable {
  91.        public void run() {
  92.           if (logTimers) {
  93.              System.out.println("Timer ringing: " + Timer.this);
  94.           }
  95.       if(eventQueued) {
  96.          fireActionPerformed(new ActionEvent(Timer.this, 0, null));
  97.          cancelEvent();
  98.          }
  99.        }
  100.  
  101.        Timer getTimer() {
  102.        return Timer.this;
  103.        }
  104.     }
  105.  
  106.     /**
  107.      * Adds an actionListener to the Timer
  108.      */
  109.     public void addActionListener(ActionListener listener) {
  110.         listenerList.add(ActionListener.class, listener);
  111.     }
  112.  
  113.     /**
  114.      * Removes an ActionListener from the Timer.
  115.      */
  116.     public void removeActionListener(ActionListener listener) {
  117.         listenerList.remove(ActionListener.class, listener);
  118.     }
  119.  
  120.     /*
  121.      * Notify all listeners that have registered interest for
  122.      * notification on this event type.  The event instance 
  123.      * is lazily created using the parameters passed into 
  124.      * the fire method.
  125.      * @see EventListenerList
  126.      */
  127.     protected void fireActionPerformed(ActionEvent e) {
  128.     // Guaranteed to return a non-null array
  129.     Object[] listeners = listenerList.getListenerList();
  130.     // Process the listeners last to first, notifying
  131.     // those that are interested in this event
  132.     for (int i = listeners.length-2; i>=0; i-=2) {
  133.         if (listeners[i]==ActionListener.class) {
  134.         ((ActionListener)listeners[i+1]).actionPerformed(e);
  135.         }           
  136.     }
  137.     }
  138.     
  139.     /** Returns the timer queue. */
  140.     TimerQueue timerQueue() {
  141.         return TimerQueue.sharedInstance();
  142.     }
  143.  
  144.     public static void setLogTimers(boolean flag) {
  145.         logTimers = flag;
  146.     }
  147.  
  148.     public static boolean getLogTimers() {
  149.         return logTimers;
  150.     }
  151.  
  152.     /** Sets the Timer's delay, the number of milliseconds between successive
  153.       * <b>actionPerfomed()</b> messages to its listeners
  154.       * @see #setInitialDelay
  155.       */
  156.     public void setDelay(int delay) {
  157.         TimerQueue queue;
  158.  
  159.         if (delay < 0) {
  160.             throw new RuntimeException("Invalid initial delay: " + delay);
  161.         }
  162.         this.delay = delay;
  163.  
  164.         if (isRunning()) {
  165.             queue = timerQueue();
  166.             queue.removeTimer(this);
  167.             cancelEvent();
  168.             queue.addTimer(this, System.currentTimeMillis() + delay);
  169.         }
  170.     }
  171.  
  172.     /** Returns the Timer's delay.
  173.       * @see #setDelay
  174.       */
  175.     public int getDelay() {
  176.         return delay;
  177.     }
  178.  
  179.     /** Sets the Timer's initial delay.  This will be used for the first
  180.       * "ringing" of the Timer only.  Subsequent ringings will be spaced
  181.       * using the delay property.
  182.       * @see #setDelay
  183.       */
  184.     public void setInitialDelay(int initialDelay) {
  185.         if (initialDelay < 0) {
  186.             throw new RuntimeException("Invalid initial delay: " +
  187.                                           initialDelay);
  188.         }
  189.         this.initialDelay = initialDelay;
  190.     }
  191.  
  192.     /** Returns the Timer's initial delay.
  193.       * @see #setDelay
  194.       */
  195.     public int getInitialDelay() {
  196.         return initialDelay;
  197.     }
  198.  
  199.     /** If <b>flag</b> is <b>false</b>, instructs the Timer to send
  200.       * <b>actionPerformed()</b> to its listeners only once, and then stop.
  201.       */
  202.     public void setRepeats(boolean flag) {
  203.         repeats = flag;
  204.     }
  205.  
  206.     /** Returns <b>true</b> if the Timer will send a <b>actionPerformed()</b>
  207.       * message to its listeners multiple times.
  208.       * @see #setRepeats
  209.       */
  210.     public boolean isRepeats() {
  211.         return repeats;
  212.     }
  213.  
  214.     /** Sets whether the Timer coalesces multiple pending ActionEvent firings.
  215.       * A busy application may not be able
  216.       * to keep up with a Timer's message generation, causing multiple
  217.       * <b>actionPerformed()</b> message sends to be queued.  When processed,
  218.       * the application sends these messages one after the other, causing the
  219.       * Timer's listeners to receive a sequence of <b>actionPerformed()</b>
  220.       * messages with no delay between them. Coalescing avoids this situation
  221.       * by reducing multiple pending messages to a single message send. Timers
  222.       * coalesce their message sends by default.
  223.       */
  224.     public void setCoalesce(boolean flag) {
  225.         coalesce = flag;
  226.     }
  227.  
  228.     /** Returns <b>true</b> if the Timer coalesces multiple pending
  229.       * <b>performCommand()</b> messages.
  230.       * @see #setCoalesce
  231.       */
  232.     public boolean isCoalesce() {
  233.         return coalesce;
  234.     }
  235.  
  236.     /** Starts the Timer, causing it to send <b>actionPerformed()</b> messages
  237.       * to its listeners.
  238.       * @see #stop
  239.       */
  240.     public void start() {
  241.         timerQueue().addTimer(this, System.currentTimeMillis() + getInitialDelay());
  242.     }
  243.  
  244.     /** Returns <b>true</b> if the Timer is running.
  245.       * @see #start
  246.       */
  247.     public boolean isRunning() {
  248.         return timerQueue().containsTimer(this);
  249.     }
  250.  
  251.     /** Stops a Timer, causing it to stop sending <b>actionPerformed()</b>
  252.       * messages to its Target.
  253.       * @see #start
  254.       */
  255.     public void stop() {
  256.         timerQueue().removeTimer(this);
  257.         cancelEvent();
  258.     }
  259.  
  260.     /**
  261.      * Restarts a Timer, canceling any pending firings, and causing
  262.      * it to fire with its initial dely.
  263.      */
  264.     public void restart() {
  265.         stop();
  266.         start();
  267.     }
  268.  
  269.     synchronized void cancelEvent() {
  270.     eventQueued = false;
  271.     }
  272.  
  273.     synchronized void post() {
  274.         if (eventQueued == false) {
  275.         eventQueued = true;
  276.         SwingUtilities.invokeLater(doPostEvent);
  277.     }
  278.     }
  279.  
  280. }
  281.